package com.chinawayltd.ews.sample.service.algorithm.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.chinawayltd.ews.sample.core.exception.BusinessException;
import com.chinawayltd.ews.sample.manager.openApi.CustomOpenApiManager;
import com.chinawayltd.ews.sample.mapper.TBranchConsumeTimeMapper;
import com.chinawayltd.ews.sample.mapper.TBranchMapper;
import com.chinawayltd.ews.sample.mapper.TInterfaceLogMapper;
import com.chinawayltd.ews.sample.mapper.TInterfaceParamMapper;
import com.chinawayltd.ews.sample.mapper.TLimiterMapper;
import com.chinawayltd.ews.sample.mapper.TOrderInterfaceLogMapper;
import com.chinawayltd.ews.sample.mapper.TOrderMapper;
import com.chinawayltd.ews.sample.mapper.algorithm.InterfaceLogExtendMapper;
import com.chinawayltd.ews.sample.mapper.algorithm.VehicleCustomExtendMapper;
import com.chinawayltd.ews.sample.mapper.order.OrderExtendMapper;
import com.chinawayltd.ews.sample.model.TBranch;
import com.chinawayltd.ews.sample.model.TBranchConsumeTime;
import com.chinawayltd.ews.sample.model.TBranchConsumeTimeExample;
import com.chinawayltd.ews.sample.model.TBranchExample;
import com.chinawayltd.ews.sample.model.TInterfaceLog;
import com.chinawayltd.ews.sample.model.TInterfaceParamWithBLOBs;
import com.chinawayltd.ews.sample.model.TLimiter;
import com.chinawayltd.ews.sample.model.TLimiterExample;
import com.chinawayltd.ews.sample.model.TOrder;
import com.chinawayltd.ews.sample.model.TOrderExample;
import com.chinawayltd.ews.sample.model.TOrderInterfaceLog;
import com.chinawayltd.ews.sample.model.basicInfo.VehicleCustomVO;
import com.chinawayltd.ews.sample.model.order.ExecuteDispatchVO;
import com.chinawayltd.ews.sample.service.algorithm.DispatchAlgorithmService;
import com.chinawayltd.ews.sample.util.TaskDispatchModel;
import com.chinawayltd.ews.sample.web.query.VehicleCustomGirdQuery;

/**
 * @program: greeProject
 * @description:
 * @author: xiazj
 * @create: 2018-05-09 17:12
 **/
@Service
public class DispatchAlgorithmServiceImpl implements DispatchAlgorithmService {

    @Autowired
    private VehicleCustomExtendMapper vehicleCustomExtendMapper;
    @Autowired
    private TLimiterMapper tLimiterMapper;
    @Autowired
    private TBranchConsumeTimeMapper tBranchConsumeTimeMapper;
    @Autowired
    private TBranchMapper tBranchMapper;
    @Autowired
    private CustomOpenApiManager customOpenApiManager;
    @Autowired
    private TInterfaceLogMapper tInterfaceLogMapper;
    @Autowired
    private TInterfaceParamMapper tInterfaceParamMapper;
    @Autowired
    private TOrderInterfaceLogMapper tOrderInterfaceLogMapper;
    @Autowired
    private InterfaceLogExtendMapper interfaceLogExtendMapper;
    @Autowired
    private TOrderMapper tOrderMapper;
    @Autowired
    private OrderExtendMapper orderExtendMapper;

    @Override
    @Transactional
    public void executeDispatch(ExecuteDispatchVO queryParam) throws Exception {
        final String datePattern = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
        //查询所有需要调度的订单信息
        Date beginTime = sdf.parse(queryParam.getBeginTime());
        Date endTime = sdf.parse(queryParam.getEndTime());
//        TOrderExample orderEx = new TOrderExample();
//        orderEx.createCriteria().andGenerateStatusEqualTo((byte)0)
//                .andEarlyDeliveryTimeBetween(beginTime, endTime)
//                .andTransportUnitLessThanOrEqualTo(new BigDecimal(30));//<=30
//        List<TOrder> orders = tOrderMapper.selectByExample(orderEx);
        List<TOrder> orders =orderExtendMapper.getDispatchOrder(beginTime,endTime);
        if(orders == null || orders.isEmpty()){
            throw new BusinessException("目前没有物料订单需要进行任务调度，请稍后再试！");
        }
        //查询所有车辆
        VehicleCustomGirdQuery vehicleQUery = new VehicleCustomGirdQuery();
        vehicleQUery.setHasWorkBranch(true);
        List<VehicleCustomVO> vehicles = vehicleCustomExtendMapper.listVehicleCustomByPage(vehicleQUery);
        //查询所有道路限行时间
        List<TLimiter> limiters = tLimiterMapper.selectByExample(new TLimiterExample());
        //查询所有站点间耗时信息
        List<TBranchConsumeTime> branchConsumeTimes = tBranchConsumeTimeMapper.selectByExample(new TBranchConsumeTimeExample());
        //查询所有站点信息
        List<TBranch> branches = tBranchMapper.selectByExample(new TBranchExample());
        //生成接口需要的传参信息
        TaskDispatchModel dispatchModel = new TaskDispatchModel.Builder().orders(orders)
                .vehicles(vehicles).limiters(limiters).branchConsumeTimes(branchConsumeTimes)
                .branches(branches).build();
        this.algorithmRun(dispatchModel, beginTime, endTime);
    }

    @Override
    @Transactional
    public String algorithmRun(TaskDispatchModel dispatchModel, Date beginTime, Date endTime) throws Exception {
        if(dispatchModel == null){
            throw new NullPointerException("dispatchModel must be not null!");
        }else if(!isReadyAlgorithmRun()){
            throw new BusinessException("目前还在进行任务调度，请稍后再进行该操作!");
        }
        customOpenApiManager.milkRunCall(dispatchModel.getToken(), dispatchModel.getData());
        insertLog(dispatchModel,beginTime, endTime);
        updateOrderStatus(dispatchModel);
        return dispatchModel.getToken();
    }

    /**
     * 更新进入到任务调度的物料订单生成状态
     * @param dispatchModel
     */
    private void updateOrderStatus(TaskDispatchModel dispatchModel) {
        Set<Long> orderIds = dispatchModel.getOrderIds();
        orderExtendMapper.updateSchedulingOrderStatusByIds(orderIds);
    }

    /**
     * 检查当前是否还有算法在执行
     * @return
     */
    public boolean isReadyAlgorithmRun(){
        boolean result = false;
        Integer unfinishedTasks = interfaceLogExtendMapper.countUnfinishedTask();
        if(unfinishedTasks == 0)result = true;
        return result;
    }

    /**
     * 插入接口日志信息
     * @param dispatchModel
     * @param endTime 
     * @param beginTime 
     */
    private void insertLog(TaskDispatchModel dispatchModel, Date beginTime, Date endTime) {
        Set<Long> orderIds = dispatchModel.getOrderIds();
        final Date now = new Date();

        //插入任务调度接口日志
        TInterfaceLog log = new TInterfaceLog();
        log.setToken(dispatchModel.getToken());
        log.setStartTime(now);
        log.setOrderStartTime(beginTime);
        log.setOrderEndTime(endTime);
        log.setRateProgress((byte)0);
        log.setIsFinish((byte)0);
        log.setCreateTime(now);
        log.setUpdateTime(now);
        tInterfaceLogMapper.insert(log);

        //插入任务调度接口日志调用参数表
        TInterfaceParamWithBLOBs param = new TInterfaceParamWithBLOBs();
        param.setId(log.getId());
        param.setInterfaceParam(dispatchModel.getData());
        param.setCreateTime(now);
        param.setUpdateTime(now);
        tInterfaceParamMapper.insert(param);

        //插入接口日志与订单的中间表
        orderIds.forEach(orderId -> {
            TOrderInterfaceLog temp = new TOrderInterfaceLog();
            temp.setLogId(log.getId());
            temp.setMaterielOrderId(orderId);
            temp.setCreateTime(now);
            temp.setUpdateTime(now);
            tOrderInterfaceLogMapper.insert(temp);
        });
    }

	@Override
	public TInterfaceLog getTaskDispatch() {
		return interfaceLogExtendMapper.getLastInterface();
	}

	@Override
    @Transactional
	public void updateTaskDispatch() throws Exception {
        //将调度的订单调度状态改回为未调度
        interfaceLogExtendMapper.updateDispatchOrderGenerateStatus();
        TInterfaceLog lastInterface = interfaceLogExtendMapper.getLastInterface();
        if(lastInterface != null && lastInterface.getIsFinish() == 0){
            customOpenApiManager.milkRunInterrupt(lastInterface.getToken());

            //取消任务调度
            lastInterface.setIsFinish((byte)2);
            lastInterface.setUpdateTime(new Date());
            tInterfaceLogMapper.updateByPrimaryKey(lastInterface);
        }

	}

}
